from datetime import datetime
from typing import Optional, List
from fastapi import APIRouter, Query, Path, HTTPException, Depends
from fastapi.responses import StreamingResponse
import io
import csv
from tortoise.functions import Count
from tortoise.expressions import Q
from backend.models.request_log import RequestLog, LoginHistory
from backend.schemas.response import ResponseBase, ResponseList
from backend.common.jwt import get_current_user
from backend.services.login_history_service import LoginHistoryService

router = APIRouter()


@router.get("/request-logs", response_model=ResponseList[dict])
async def get_request_logs(
    page: int = Query(1, description="页码"),
    limit: int = Query(10, description="每页数量"),
    ip_address: Optional[str] = Query(None, description="IP地址"),
    path: Optional[str] = Query(None, description="请求路径"),
    method: Optional[str] = Query(None, description="请求方法"),
    status_code: Optional[int] = Query(None, description="状态码"),
    start_date: Optional[str] = Query(None, description="开始日期"),
    end_date: Optional[str] = Query(None, description="结束日期"),
    _=Depends(get_current_user)
):
    """
    获取请求日志列表，支持分页和筛选
    """
    # 构建查询条件
    query = RequestLog.all()
    
    if ip_address:
        query = query.filter(ip_address__contains=ip_address)
    if path:
        query = query.filter(path__contains=path)
    if method:
        query = query.filter(method=method)
    if status_code:
        query = query.filter(status_code=status_code)
    
    # 处理日期范围
    if start_date:
        try:
            # 检查是否已包含时间部分
            if " " in start_date and len(start_date) > 10:
                # 日期字符串已包含时间部分，直接解析
                start_datetime = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
            else:
                # 仅包含日期，添加默认的开始时间 00:00:00
                start_datetime = datetime.strptime(f"{start_date} 00:00:00", "%Y-%m-%d %H:%M:%S")
            query = query.filter(request_time__gte=start_datetime)
        except ValueError as e:
            raise HTTPException(status_code=422, detail=f"开始日期格式不正确: {e}")
            
    if end_date:
        try:
            # 检查是否已包含时间部分
            if " " in end_date and len(end_date) > 10:
                # 日期字符串已包含时间部分，直接解析
                end_datetime = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
            else:
                # 仅包含日期，添加默认的结束时间 23:59:59
                end_datetime = datetime.strptime(f"{end_date} 23:59:59", "%Y-%m-%d %H:%M:%S")
            query = query.filter(request_time__lte=end_datetime)
        except ValueError as e:
            raise HTTPException(status_code=422, detail=f"结束日期格式不正确: {e}")
    
    # 获取总数
    total = await query.count()
    
    # 分页
    logs = await query.order_by("-request_time").offset((page - 1) * limit).limit(limit).values()
    
    return ResponseList(data=logs, total=total)


@router.get("/request-logs/export")
async def export_request_logs(
    ip_address: Optional[str] = Query("", description="IP地址"),
    path: Optional[str] = Query("", description="请求路径"),
    method: Optional[str] = Query("", description="请求方法"),
    status_code: Optional[int] = Query(None, description="状态码"),
    start_date: Optional[str] = Query(None, description="开始日期"),
    end_date: Optional[str] = Query(None, description="结束日期"),
    _=Depends(get_current_user)
):
    """
    导出请求日志
    """
    # 构建查询条件
    query = RequestLog.all()
    
    if ip_address:
        query = query.filter(ip_address__contains=ip_address)
    if path:
        query = query.filter(path__contains=path)
    if method:
        query = query.filter(method=method)
    if status_code:
        query = query.filter(status_code=status_code)
    
    # 处理日期范围
    if start_date:
        try:
            # 检查是否已包含时间部分
            if " " in start_date and len(start_date) > 10:
                # 日期字符串已包含时间部分，直接解析
                start_datetime = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S")
            else:
                # 仅包含日期，添加默认的开始时间 00:00:00
                start_datetime = datetime.strptime(f"{start_date} 00:00:00", "%Y-%m-%d %H:%M:%S")
            query = query.filter(request_time__gte=start_datetime)
        except ValueError as e:
            raise HTTPException(status_code=422, detail=f"开始日期格式不正确: {e}")
            
    if end_date:
        try:
            # 检查是否已包含时间部分
            if " " in end_date and len(end_date) > 10:
                # 日期字符串已包含时间部分，直接解析
                end_datetime = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
            else:
                # 仅包含日期，添加默认的结束时间 23:59:59
                end_datetime = datetime.strptime(f"{end_date} 23:59:59", "%Y-%m-%d %H:%M:%S")
            query = query.filter(request_time__lte=end_datetime)
        except ValueError as e:
            raise HTTPException(status_code=422, detail=f"结束日期格式不正确: {e}")
    
    # 获取所有符合条件的日志
    logs = await query.order_by("-request_time").values()
    
    # 创建CSV文件
    output = io.StringIO()
    writer = csv.writer(output)
    
    # 写入表头
    writer.writerow(["ID", "请求时间", "IP地址", "浏览器", "请求路径", "请求方法", "状态码", "User Agent", "请求参数"])
    
    # 写入数据
    for log in logs:
        writer.writerow([
            log["id"],
            log["request_time"].strftime("%Y-%m-%d %H:%M:%S") if log["request_time"] else "",
            log["ip_address"] or "",
            log["browser"] or "",
            log["path"] or "",
            log["method"] or "",
            log["status_code"] or "",
            log["user_agent"] or "",
            str(log["params"]) if log["params"] else ""
        ])
    
    # 重置指针位置
    output.seek(0)
    
    # 设置响应头
    filename = f"request_logs_{datetime.now().strftime('%Y%m%d%H%M%S')}.csv"
    headers = {
        'Content-Disposition': f'attachment; filename="{filename}"'
    }
    
    # 返回CSV文件
    return StreamingResponse(
        iter([output.getvalue()]),
        media_type="text/csv",
        headers=headers
    )


@router.get("/request-logs/{log_id}", response_model=ResponseBase[dict])
async def get_request_log_detail(
    log_id: int = Path(..., description="日志ID"),
    _=Depends(get_current_user),
):
    """
    获取请求日志详情
    """
    log = await RequestLog.get_or_none(id=log_id)
    if not log:
        raise HTTPException(status_code=404, detail="日志不存在")
    
    return ResponseBase(data=dict(log))


@router.get("/request-logs/stats", response_model=ResponseBase[dict])
async def get_request_logs_stats(_=Depends(get_current_user)):
    """
    获取请求日志统计数据
    """
    # 获取总请求数
    total_requests = await RequestLog.all().count()
    
    # 获取今日请求数
    today = datetime.now().date()
    today_start = datetime.combine(today, datetime.min.time())
    today_requests = await RequestLog.filter(request_time__gte=today_start).count()
    
    # 获取各状态码的请求数
    status_stats = await RequestLog.all().annotate(
        count=Count('id')
    ).group_by('status_code').values('status_code', 'count')
    
    # 获取各请求方法的请求数
    method_stats = await RequestLog.all().annotate(
        count=Count('id')
    ).group_by('method').values('method', 'count')
    
    # 获取最近7天的请求趋势
    # 这里简化处理，实际可能需要更复杂的SQL查询
    seven_days_ago = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
    seven_days_ago = seven_days_ago.replace(day=seven_days_ago.day - 7)
    
    recent_logs = await RequestLog.filter(
        request_time__gte=seven_days_ago
    ).values('request_time')
    
    # 简化处理，按日期分组统计
    daily_counts = {}
    for log in recent_logs:
        date_str = log['request_time'].strftime('%Y-%m-%d')
        if date_str in daily_counts:
            daily_counts[date_str] += 1
        else:
            daily_counts[date_str] = 1
    
    # 转换为前端需要的格式
    trend_data = [
        {"date": date, "count": count} for date, count in daily_counts.items()
    ]
    
    return ResponseBase(data={
        "total_requests": total_requests,
        "today_requests": today_requests,
        "status_stats": status_stats,
        "method_stats": method_stats,
        "trend_data": trend_data
    })


@router.get("/login-history", response_model=ResponseList[dict])
async def get_login_history(
    page: int = Query(1, description="页码"),
    limit: int = Query(10, description="每页数量"),
    username: Optional[str] = Query(None, description="用户名"),
    ip_address: Optional[str] = Query(None, description="IP地址"),
    status: Optional[str] = Query(None, description="登录状态"),
    start_date: Optional[str] = Query(None, description="开始日期"),
    end_date: Optional[str] = Query(None, description="结束日期"),
    _=Depends(get_current_user)
):
    """
    获取登录历史列表，支持分页和筛选
    """
    records, total = await LoginHistoryService.get_login_history(
        page=page,
        limit=limit,
        username=username,
        ip=ip_address,
        status=status,
        start_date=start_date,
        end_date=end_date
    )
    
    # 构造返回数据
    data = []
    for record in records:
        data.append({
            "id": record.id,
            "username": record.user.username if record.user else "未知用户",
            "ip": record.ip_address,
            "location": record.location or "未知",
            "device": record.device or "未知",
            "browser": record.browser or "未知",
            "os": record.os or "未知",
            "login_time": record.login_time.strftime("%Y-%m-%d %H:%M:%S"),
            "status": record.status
        })
    
    return ResponseList(data=data, total=total)


@router.get("/login-history/stats", response_model=ResponseBase[dict])
async def get_login_history_stats(_=Depends(get_current_user)):
    """
    获取登录统计数据
    """
    stats = await LoginHistoryService.get_stats()
    return ResponseBase(data=stats)


@router.get("/login-history/trend", response_model=ResponseBase[dict])
async def get_login_history_trend(
    trend_type: str = Query("week", description="趋势类型: week或month"),
    _=Depends(get_current_user)
):
    """
    获取登录趋势数据
    """
    trend_data = await LoginHistoryService.get_trend_data(trend_type)
    return ResponseBase(data=trend_data)
